import Cesium from '../Ces/Cesium'
import WeDisplayShaders from '../Display/WeDisplayShaders'
import { vsSource, fsSource } from './FluidMeshShaders'
import FluidParameter from './FluidParameter'

class FluidMesh {
  fluidParameter: FluidParameter
  drawCommand: any//Cesium.DrawCommand
  constructor({
    lastWater,
    fluidParameter,
    fluidNeighbor, terrainTexture,
    currentWater, fluidUniform, flows
  }, context) {
    this.fluidParameter = fluidParameter

    const { width, height } = fluidUniform
    const { vertexArray, attributeLocations } = this.fluidParameter.getVertexArray(context, width, height)

    const uniformSource1 = fluidUniform.getSource()
    const uniformSource2 = fluidNeighbor.getSource()
    const uniformSource3 = fluidParameter.getSource()

    const vertexShaderSource = `
      ${WeDisplayShaders.WeCartesian3FromRadians}
      ${uniformSource1}
      ${uniformSource2}
      ${uniformSource3}
      ${vsSource}
    `

    const fragmentShaderSource = `
      ${WeDisplayShaders.WePhong}
      ${uniformSource1}
      ${uniformSource2}
      ${uniformSource3}
      ${fsSource}
    `

    const shaderProgram = Cesium.ShaderProgram.fromCache({
      context,
      vertexShaderSource,
      fragmentShaderSource,
      attributeLocations,
    })

    const renderState = Cesium.RenderState.fromCache({
      cull: {
        enabled: true,
        face: Cesium.CullFace.BACK,
      },
      depthTest: {
        enabled: true,
      },
    })

    const translucent = true
    const uniformMap = {
      terrainTex: () => terrainTexture,
      currentWater: () => currentWater,
      lastWater: () => lastWater,
      flows: () => flows,
      normalMap: () => fluidParameter.getNormalTex(context),
    }

    fluidUniform.setupUniformMap(uniformMap)
    fluidNeighbor.setupUniformMap(uniformMap)
    fluidParameter.setupUniformMap(uniformMap)

    const position = fluidUniform.rtcCenter
    const modelMatrix = Cesium.Matrix4.fromTranslation(position, new Cesium.Matrix4())

    this.drawCommand = new Cesium.DrawCommand({
      vertexArray,
      shaderProgram,
      uniformMap,
      renderState,
      pass: translucent ? Cesium.Pass.TRANSLUCENT : Cesium.Pass.OPAQUE,
      modelMatrix,
    })
  }

  update(frameState) {
    frameState.commandList.push(this.drawCommand)
  }

  destroy() {
    if (this.drawCommand) {
      this.drawCommand.vertexArray = this.drawCommand.vertexArray &&
        this.drawCommand.vertexArray.destroy()
      this.drawCommand.shaderProgram = this.drawCommand.shaderProgram &&
        this.drawCommand.shaderProgram.destroy()
    }
    this.drawCommand = undefined
    return Cesium.destroyObject(this)
  }

  isDestroyed() {
    return false
  }
}

export default FluidMesh
